线上大爆发,移动订单量占比达83%,归功于苏宁易购移动端统一接入层!
近几年,苏宁易购随着业务的发展,用户使用习惯的改变,不断强化移动端发展,加强与视频直播,娱乐、体育营销等各类内容媒体的合作,创新营销产品,不断提升移动端日活,2017 年 3 月移动端订单数量已占线上整体比例的 83%。
为了进一步提高移动端访问速度,提升用户体验,移动团队潜心研究网关、http2.0技术,最终决定上线统一接入层。
下面从三个方面解析苏宁易购移动端统一接入层:
统一接入层设计
统一接入层的功能、实现
统一接入层的性能
统一接入层的设计
苏宁易购的架构演进
苏宁易购的网络架构不断发展演进,2014 年接入应用防火墙,为 Web 应用提供安全保护。2015 - 2016 年,整体架构更加健壮稳定,保障了业务需求,支撑了线上业务的飞速发展。
2017 年,随着统一接入层的加入,系统封装了应用程序的内部结构。客户端只需要同网关交互,而不必调用特定的服务。并在此基础上,系统做了域名收敛,使用 http2.0 协议,重点提高了移动端的访问速度。
统一接入层的架构划分
统一接入层的架构划分图
统一接入层内部架构分为三层:
代理层,有多台代理 proxy,由 go 语言实现,将请求向后转发;
一个个虚拟的集群,每个集群对应一个业务系统,并且管理着系统的服务器;
服务器,该服务器为目前线上各个系统的服务器。配置信息存储在 zookeeper 上,后台管理系统对 zookeeper 上的配置数据进行统一的管理。
统一接入层内部架构图
从上往下,统一接入层对移动端的请求做了接管,然后转发到相应的服务器上去。代理层用 go 语言实现,主要是利用 go 的高性能,以及线程无限制。后台管理系统使用 Java 实现,为了统一管理,使用公司内部 passport、统一后台管理等。
统一接入层内部组件图
目前,移动端系统接入统一接入层后,iOS 和 Android 客户端发出的请求全部收敛为一个域名,并且走 http2.0 协议。请求经 CDN 到达代理层 proxy,proxy 再将请求转发到各个集群系统,回源协议支持 http2.0,http1.1。
统一接入层网络架构
统一接入层功能、实现
统一接入层的一项重要功能是转发请求,我们首先考虑基于 Nginx 做整个代理层,但综合分析,其与我们团队技术方向不一致,修改 Nginx 成本较高,不便于定制个性化需求。
然后,我们选择使用 go 语言,一是被其简洁的语法所吸引,二是其性能确实强悍,后期的压测数据,也证实了这一点,让我们感到惊喜。
技术实现方案
下面介绍在整个实现过程中,我们应用的技术点,和接入层具备的功能:
采用高效的 fasthttp 组件做请求接入和转发层,性能直逼 Ngnix,经过测试每个转发请求包括网络传输平均只增加了 0.1 毫秒。
fasthttp是 Go 的一款不同于标准库 net/http 的 HTTP 实现,其性能可以达到标准库的 10 倍。
在匹配路由规则上,通过快速查找算法和精准匹配算法的互补,可以既保证性能又保证准确性。
在对后端请求的转发上,使用 TCP 链路复用的方式,使得请求在转发层面上犹如同一台机器,大量的减少网络交互。
对于后端服务的检活,是用主动检活加被动检活相结合的方式,提高了对后端服务快速容错的能力。
所有的规则配置通过 zookeeper 快速配置,可以实现线上配置实时生效的功能。
对于内部组件 filter 层,使用的 go 1.8 支持的 plugin 的方式,通过线上动态打补丁的方式来支持新需求的功能增加。
整个 proxy 基本是无状态的,对 zookeeper 部署上也考虑了多机房同步的方案,所以整个统一接入层也具备多机房部署能力。
支持修改请求的 HOST,统一接入层修改了请求的域名,但一些系统的 Apache 上针对原域名有配置,尤其是需要登录的接口。
为应对这一点,支持在后台配置请求的原始域名,proxy 转发时,HOST 的值为原始域名,这样一来,请求就能正确的响应,并且原系统不需要修改服务器配置,对接入层无感知。
转发规则动态配置
所有配置数据(转发规则)存放在 zookeeper 上,支持动态配置,由后台管理系统统一管理。
代理(proxy),代理机器在 zookeeper 注册临时节点,如果代理机器与 zookeeper 的连接断开,临时节点自动删除,利用临时节点的特性检活 proxy。
转发规则(api),存放的是 url 的路由规则,如下图,统一接入层根据url转发,将匹配 / mtspre /* 的请求,转发到集群 mtspre,并且重写转发后的请求地址。
转发规则
集群(cluster),存放每个集群的信息,集群中包含的服务器和转发策略,支持随机和哈希两种方式。
集群信息
服务器(server),存放所有服务器的信息,包括检活周期和超时时间。
绑定关系(bind),存放集群和服务器的绑定关系。
proxy 代理层监听 zookeeper 的每一个节点,一旦节点数据发生变化,可以实时的获取最新的配置,立即生效,改变请求的路由策略。
为了保证可靠性,应对 zookeeper 所在的虚拟机宕机,所有配置信息入库,并且写文件,极端情况下,proxy可以从文件中读取配置信息,正常启动。
协议
移动端发出的请求统一走 http2.0 协议,Android 端使用 okhttp 实现,iOS 端使用 AFNetworking。
相比 HTTP/1.x,HTTP/2,系统在底层传输做了很大的改动和优化:
HTTP/2 采用二进制格式传输数据,而非 HTTP/1.x 的文本格式。
HTTP/2 对消息头采用 HPACK 进行压缩传输,能够节省消息头占用的网络流量。而 HTTP/1.x 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。
多路复用,直白的说就是所有的请求都是通过一个 TCP 连接并发完成。同时,流还支持优先级和流量控制。
Server Push:服务端能够更快的把资源推送给客户端。例如服务端可以主动把 JS 和 CSS 文件推送给客户端。
HTTP/2 主要是 HTTP/1.x 在底层传输机制上的完全重构,HTTP/2 是基本兼容 HTTP/1.x 的语义。Content-Type 仍然是 Content-Type,只不过它不再是文本传输了。
域名收敛
接入统一接入层后,客户端使用到的域名都收敛成一个域名,域名后面的第一个目录,标记了该请求所属的系统,即路由规则,程序员据此将请求转发到不同的系统。客户端收敛域名,不仅有效的减少首次访问的DNS解析次数,最主要的是为了充分利用 http2.0 的特性——多路复用。
因为只有一个域名,所有请求只需要建立一条连接即可发送完毕,大大减少等待时间,真正实现并发。如下图所示的链路复用,只进行了一次 ssl 握手(紫色部分),其他请求复用此链路,并且同时发出。
后端服务器检活
做请求转发,检查后端 server 的健康性非常重要,我们目前有两套检活方案,同时运行。
(1)前台代理层 proxy 被动检活
proxy 向后端服务器转发请求,如果返回失败,则将这台服务器的 checkFailCount 加1,checkFailCount 超过 3,就会将服务器标记为 down,不再向它发起转发请求。默认检活超时是 3s,3s 之内,后端 server 没有再次返回失败,将 checkFailCount 清零。
(2)后台管理系统主动检活
后台主动检活,在后台管理系统启动时便开始运行,可以设置检活周期和超时时间。检活线程根据服务器的 IP 及端口号,主动与每一台服务器建立 socket 连接,建立连接超时则认为服务器不可用,将其状态标记为 down;成功建立连接,则将状态标记为 up。
前后主动、被动检活的结合,保证了在服务器不可用的时候,停止向其转发请求。同时,在服务器重新可用时,将其状态标记为up,前台proxy可以继续向其转发请求。
开关
(1)降级开关
为了保证可靠性,统一接入层修改了原有的网络链路,上线必须有降级开关。目前,我们设计了一套开关,可以针对 APP 版本号,以及操作系统类型设置开关的状态。
开关打开时,将原域名转换成收敛后的域名,请求走统一接入层;关闭开关,域名恢复成原域名,请求不经过统一接入层,直接走原链路,支持线上实时切换。
(2)协议转换开关
http2.0 的应用还在起步阶段,目前网络链路上存在一定的风险,这是我们所不能接受的,为此设计了另外一套开关,可以将协议在 http2.0 和 http1.1 之间切换,将风险降低到最低。
统一接入层性能
系统性能
为了测试统一接入层的性能,能否达到上线要求。移动团队对苏宁易购 APP 端的生产接口进行了压测,场景 1 是请求走原始链路,场景 2 是请求经过统一接入层,压测数据如下。
原始链路请求
统一接入层转发请求
请求走原始链路,平均 tps 为 9130,平均响应时间是 11 ms,通过统一接入层的请求,tps 达到 14200,提高了 50%,响应时间 6ms,缩短了近一半。这得益于 go 语言的高性能,快速路由选择算法,以及后端 tcp 连接的复用。
真实用户数据采集
为了提高系统的访问性能,也为了检验统一接入层在实际生产环境中的表现,我们将部分接口接入了统一接入层,运行到生产环境中,经过不间断的监控,我们采集到了真实的用户数据。
未接入统一接入层的接口,请求数据:
原始链路接口
接入统一接入层的接口,请求数据:
接入统一接入层的接口
图 1 为原始链路接口的 top99,71% 的请求平均响应时间为 72ms,图 2 是接入统一接入层的接口,域名收敛,协议走 http2.0,然后经过系统的 proxy 转发,87% 的请求平均响应时间为 62ms,top99 数据有明显的提高。
结语
本文主要分享了统一接入层的技术实现方案和功能,利用 go 语言的快速、高效、高性能,搭上 http2.0 的快车,为用户提供更好的购物体验。上线以来,通过 24 小时不间断监控和采集数据,统一接入层功能稳定,性能提升了 20% 左右,达到了我们的预期。
但是,目前统一接入层处于起步阶段,移动团队最终的目标是接入核心系统 80% 以上的请求,将移动端访问性能提升 30% 以上。相信通过团队的共同努力,不断创新,移动端性能还可以有更大的提升。
作者:任良成、王一硼
编辑:孙淑娟
任良成
苏宁云商 IT 总部架构师
主要承担苏宁易购 https 改造,负责统一接入层上线,在网络性能优化方面有很深的思考和领悟,现正和研发团队一起建设统一接入层,持续优化网关层,做出更高效稳健的网关。
王一硼
苏宁云商 IT 总部高级架构师
拥有多年 IT 平台研发和管理工作经验,先后在苏宁,阿里,惠普等大型互联网和 IT 企业工作,对 SOA 企业架构,高并发高可用的系统设计有多年的实战经验,专注于分布式,高并发,高性能/性能调优,架构拆分和整合,大数据等技术领域。
精彩文章推荐: